package com.yanqu.road.server.manager.beautyescort;

import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.entity.rank.cross.CrossUnionWeekRank;
import com.yanqu.road.entity.servercenter.ServerInfo;
import com.yanqu.road.entity.task.args.UnionRiseRankArgs;
import com.yanqu.road.entity.union.UnionBaseInfo;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.logic.pb.UnionBasePb;
import com.yanqu.road.pb.beautyescort.BeautyEscortProto;
import com.yanqu.road.pb.common.CommonProto;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.server.manager.user.CrossUserMgr;
import com.yanqu.road.server.manger.ServerListMgr;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.ConfigHelper;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigInteger;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class CrossBeautyEscortCacheMgr extends TempMgr {

    //weekId, unionUid
    static Map<Integer, Map<String, CrossBeautyEscortUnion>> unionValueCacheMap = new ConcurrentHashMap<>();

    //区服上传标识
    static Map<Long, Boolean> serverUploadMarkMap = new ConcurrentHashMap<>();

    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    @Override
    public boolean reloadData() throws Exception {
        return true;
    }

    @Override
    public boolean stop() {
        return true;
    }

    /**
     * 增加区服商会信息
     * @param weekId  周
     * @param serverData  区服商会/商会成员数据
     */
    public static void addCrossBeautyEscortUnion(int weekId, Map<String, CrossBeautyEscortUnion> serverData){
        Map<String, CrossBeautyEscortUnion> map = unionValueCacheMap.get(weekId);
        if(map == null){
            synchronized (unionValueCacheMap) {
                map = unionValueCacheMap.get(weekId);
                if (map == null) {
                    map = new ConcurrentHashMap<>();
                    unionValueCacheMap.put(weekId, map);
                }
            }
        }
        synchronized (map){
            for (Map.Entry<String, CrossBeautyEscortUnion> unionEntry : serverData.entrySet()) {
                String unionUid =unionEntry.getKey();
                CrossBeautyEscortUnion updateUnion = unionEntry.getValue();
                if(map.containsKey(unionUid)){
                    CrossBeautyEscortUnion oldUnion = map.get(unionEntry.getKey());
                    for (CrossBeautyEscortUser updateUser : updateUnion.getUserList()) {
                        boolean exist = false;
                        for (int i = 0; i < oldUnion.getUserList().size(); i++) {
                            CrossBeautyEscortUser oldUser = oldUnion.getUserList().get(i);
                            if(updateUser.getUserId() == oldUser.getUserId()){
                                oldUser.setModifyTime(updateUser.getModifyTime());
                                oldUser.setValue(updateUser.getValue());
                                exist = true;
                                break;
                            }
                        }
                        if(!exist){
                            synchronized (oldUnion) {
                                oldUnion.getUserList().add(updateUser);
                            }
                        }
                    }
                }else {
                    map.put(unionUid, updateUnion);
                }

                CrossBeautyEscortUnion oldUnion = map.get(unionEntry.getKey());
                long sum = 0;
                for (int i = 0; i < oldUnion.getUserList().size(); i++) {
                    CrossBeautyEscortUser user = oldUnion.getUserList().get(i);
                    sum += user.getValue();
                }
                oldUnion.setValue(sum);
            }
        }
    }

    public static CrossBeautyEscortUnion getAndCheckCrossBeautyEscortUnion(int weekId, String unionUid){
        Map<String, CrossBeautyEscortUnion> map = unionValueCacheMap.get(weekId);
        if(map == null){
            synchronized (unionValueCacheMap) {
                map = unionValueCacheMap.get(weekId);
                if (map == null) {
                    map = new ConcurrentHashMap<>();
                    unionValueCacheMap.put(weekId, map);
                }
            }
        }
        CrossBeautyEscortUnion union = map.get(unionUid);
        if(union == null){
            synchronized (map){
                union = map.get(unionUid);
                if(union == null){
                    union = new CrossBeautyEscortUnion();
                    union.setUnionUid(unionUid);
                    union.setWeekId(weekId);
                    map.put(unionUid, union);
                }
            }
        }
        return union;
    }

    public static CrossBeautyEscortUser getCrossBeautyEscortUser(int weekId, long userId, String unionUid){
        if(StringUtils.isNullOrEmpty(unionUid)){
            return null;
        }else {
            Map<String, CrossBeautyEscortUnion> map = unionValueCacheMap.get(weekId);
            if(map == null){
                return null;
            }
            CrossBeautyEscortUnion union = map.get(unionUid);
            if(union == null){
                return null;
            }
            for (int i = 0; i < union.getUserList().size(); i++) {
                CrossBeautyEscortUser user = union.getUserList().get(i);
                if(user.getUserId() == userId){
                    return user;
                }
            }
        }
        return null;
    }

    public static CrossBeautyEscortUnion getCrossBeautyEscortUnion(int weekId, String unionUid){
        Map<String, CrossBeautyEscortUnion> map = unionValueCacheMap.get(weekId);
        if(map == null){
            return null;
        }
        return map.get(unionUid);
    }
    /**
     * 通知区服上传榜单数据
     */
    public static void notifyServerUploadData(){
        int channelId = ConfigHelper.getInt("channelId");
        List<ServerInfo> serverInfoList = ServerListMgr.getChannelServerList(channelId);
        for (ServerInfo info : serverInfoList) {
            if(serverUploadMarkMap.containsKey(info.getServerId())){
                if(serverUploadMarkMap.get(info.getServerId())){
                    continue;
                }
            }
            MessageHelper.sendPacket(info.getServerId(), 0, YanQuMessageUtils.buildMessage(Protocol.S_BEAUTY_ESCORT_NOTIFY_UPLOAD_VALUE_FROM_CROSS, CommonProto.NullValueMsg.newBuilder()));
        }
    }

    public static void addServerUploadData(BeautyEscortProto.BeautyEscortUploadValueMsg uploadValueMsg, long serverId) {

        for (BeautyEscortProto.BeautyEscortWeekValueTemp weekValueTemp : uploadValueMsg.getWeekList()) {
            int weekId = weekValueTemp.getWeekId();
            Map<String, CrossBeautyEscortUnion> unionMap = new HashMap<>();
            for (BeautyEscortProto.BeautyEscortWeekUnionValueTemp unionValueTemp : weekValueTemp.getUnionList()) {
                String unionUid = unionValueTemp.getUnionUid();
                CrossBeautyEscortUnion union = new CrossBeautyEscortUnion();
                union.setUnionUid(unionUid);
                union.setWeekId(weekId);
                union.setUnionBaseInfo(UnionBasePb.parseUnionBaseInfo(unionValueTemp.getUnion()));

                for (BeautyEscortProto.BeautyEscortWeekUserValueTemp userValueTemp : unionValueTemp.getUserList()) {
                    CrossBeautyEscortUser user = new CrossBeautyEscortUser();
                    user.setModifyTime(userValueTemp.getModifyTime());
                    user.setUserId(userValueTemp.getUserId());
                    user.setValue(userValueTemp.getValue());
                    union.getUserList().add(user);
                }
                unionMap.put(unionUid, union);
            }

            addCrossBeautyEscortUnion(weekId, unionMap);
        }

        serverUploadMarkMap.put(serverId, true);
    }

    public static void changeUserValue(BeautyEscortProto.BeautyEscortWeekUserValueChangeMsg changeMsg) {

        if(changeMsg.getType() == UnionRiseRankArgs.NOTIFY_TYPE_NORMAL || changeMsg.getType() == UnionRiseRankArgs.NOTIFY_TYPE_JOIN){
            CrossBeautyEscortUser user = getCrossBeautyEscortUser(changeMsg.getWeekId(), changeMsg.getUserValue().getUserId(), changeMsg.getUnionUid());
            CrossBeautyEscortUnion union = getAndCheckCrossBeautyEscortUnion(changeMsg.getWeekId(), changeMsg.getUnionUid());
            UnionBaseInfo unionBaseInfo = UnionBasePb.parseUnionBaseInfo(changeMsg.getUnion());
            if(union.getUnionBaseInfo() == null){
                union.setUnionBaseInfo(unionBaseInfo);
            }
            if(user == null) {
                user = new CrossBeautyEscortUser(changeMsg.getWeekId(), changeMsg.getUserValue().getUserId(), changeMsg.getUserValue().getValue(), changeMsg.getUserValue().getModifyTime());
                addUserToUnion(union, user);
            }
            user.setValue(changeMsg.getUserValue().getValue());
            user.setModifyTime(changeMsg.getUserValue().getModifyTime());
            if(!StringUtils.isNullOrEmpty(changeMsg.getUnionUid())){
                changeUnionRank(changeMsg.getUnionUid(), changeMsg.getWeekId(), unionBaseInfo);
                //getLogger().info("add userId {} to unionUid {} rank, size {}", user.getUserId(), union.getUnionUid(), union.userList.size());
            }
        }

        if(changeMsg.getType() == UnionRiseRankArgs.NOTIFY_TYPE_REMOVE){
            CrossBeautyEscortUnion union = getCrossBeautyEscortUnion(changeMsg.getWeekId(), changeMsg.getUnionUid());
            if(union != null){
                synchronized (union) {
                   Iterator<CrossBeautyEscortUser> iterator = union.userList.iterator();
                   while (iterator.hasNext()){
                       CrossBeautyEscortUser user = iterator.next();
                       if(user.getUserId() == changeMsg.getUserValue().getUserId()){
                           iterator.remove();
                           UnionBaseInfo unionBaseInfo = UnionBasePb.parseUnionBaseInfo(changeMsg.getUnion());
                           changeUnionRank(changeMsg.getUnionUid(), changeMsg.getWeekId(), unionBaseInfo);
                           getLogger().info("remove userId {} from unionUid {} rank", user.getUserId(), union.getUnionUid());
                           break;
                       }
                   }
                }
            }
        }else if(changeMsg.getType() == UnionRiseRankArgs.NOTIFY_TYPE_DELETE){
            if(!StringUtils.isNullOrEmpty(changeMsg.getUnionUid())){
                int groupId = CrossBeautyEscortRankMgr.getGroupId(changeMsg.getUnion().getServerId());
                CrossGroupWeekUnionRankListModel model = CrossBeautyEscortRankMgr.getCrossGroupWeekUnionRankListModel(changeMsg.getWeekId(), groupId);
                if(model != null){
                    model.removeRank(changeMsg.getUnionUid());
                    getLogger().info("delete all userId from unionUid {} rank", changeMsg.getUnionUid());
                }
            }
        }

    }

    private static void addUserToUnion(CrossBeautyEscortUnion union, CrossBeautyEscortUser user) {
        for (int i = 0; i < union.getUserList().size(); i++) {
            CrossBeautyEscortUser escortUser = union.getUserList().get(i);
            if(user.getUserId() == escortUser.getUserId()){
                synchronized (union) {
                    union.getUserList().set(i, user);
                }
                return;
            }
        }
        synchronized (union) {
            union.getUserList().add(user);
        }
    }

    /**
     * 玩家冲榜
     * @param unionUid 商会
     * @param weekId  周
     */
    private static void changeUnionRank(String unionUid, int weekId, UnionBaseInfo unionBaseInfo) {
        CrossBeautyEscortUnion union = getAndCheckCrossBeautyEscortUnion(weekId, unionUid);
        if(union != null){
            long value = 0L;
            for (int i = 0; i < union.getUserList().size(); i++) {
                CrossBeautyEscortUser user = union.getUserList().get(i);
                value += user.getValue();
            }
            union.setValue(value);
            union.setUnionBaseInfo(unionBaseInfo);
            CrossUnionWeekRank unionWeekRank = new CrossUnionWeekRank();
            unionWeekRank.setUnionBaseInfo(union.getUnionBaseInfo());
            unionWeekRank.setValue(BigInteger.valueOf(value));
            unionWeekRank.setWeekId(weekId);
            unionWeekRank.setUnionUid(unionUid);
            unionWeekRank.setServerId(union.getUnionBaseInfo().getServerId());
            CrossBeautyEscortRankMgr.changeUnionRank(weekId, union.getUnionBaseInfo().getServerId(), unionWeekRank);
        }
    }

    /**
     * 成员贡献详情
     * @param weekId 周id
     * @param unionUid  商会
     * @return
     */
    public static BeautyEscortProto.BeautyEscortRankMemberDataRespMsg.Builder getRankMemberDataList(int weekId, String unionUid) {
        BeautyEscortProto.BeautyEscortRankMemberDataRespMsg.Builder respMsg = BeautyEscortProto.BeautyEscortRankMemberDataRespMsg.newBuilder();
        respMsg.setRet(0);
        Map<String, CrossBeautyEscortUnion> unionMap = unionValueCacheMap.get(weekId);
        if(unionMap != null){
            CrossBeautyEscortUnion union = unionMap.get(unionUid);
            if(union != null){
                for (int i = 0; i < union.getUserList().size(); i++) {
                    CrossBeautyEscortUser user = union.getUserList().get(i);
                    BeautyEscortProto.EscortUnionRankMemberDataTempMsg.Builder builder = BeautyEscortProto.EscortUnionRankMemberDataTempMsg.newBuilder();
                    builder.setUserId(user.getUserId());
                    builder.setValue(String.valueOf(user.getValue()));
                    builder.setModifyTime(user.getModifyTime());
                    UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(user.getUserId());
                    if(userBaseInfo != null){
                        builder.setUserBaseInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
                        respMsg.addData(builder);
                    }else {
                        //暂时不加
                        getLogger().info("get escort rank, union {}, member {} baseInfo null", union.getUnionUid(), user.getUserId());
                    }
                }
            }
        }
        return respMsg;
    }
}
